<script setup lang="ts">
import type Node from 'element-plus/es/components/tree/src/model/node'
import type { DragEvents } from 'element-plus/es/components/tree/src/model/useDragNode'
import type { AllowDropType, NodeDropType } from 'element-plus/es/components/tree/src/tree.type'

/**
 * 处理节点拖拽开始事件
 * @param node - 被拖拽的节点
 * @param ev - 拖拽事件对象
 */
const handleDragStart = (node: Node, ev: DragEvents) => {
  // console.log('drag start', node)
}

/**
 * 处理拖拽节点进入目标节点事件
 * @param draggingNode - 正在被拖拽的节点
 * @param dropNode - 目标节点
 * @param ev - 拖拽事件对象
 */
const handleDragEnter = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {
  // console.log('tree drag enter:', dropNode.label)
}

/**
 * 处理拖拽节点离开目标节点事件
 * @param draggingNode - 正在被拖拽的节点
 * @param dropNode - 目标节点
 * @param ev - 拖拽事件对象
 */
const handleDragLeave = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {
  // console.log('tree drag leave:', dropNode.label)
}

/**
 * 处理拖拽节点在目标节点上移动事件
 * @param draggingNode - 正在被拖拽的节点
 * @param dropNode - 目标节点
 * @param ev - 拖拽事件对象
 */
const handleDragOver = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {
  // console.log('tree drag over:', dropNode.label)
}

/**
 * 处理拖拽操作结束事件
 * @param draggingNode - 正在被拖拽的节点
 * @param dropNode - 目标节点
 * @param dropType - 放置类型 ('prev' | 'next' | 'inner')
 * @param ev - 拖拽事件对象
 */
const handleDragEnd = (
  draggingNode: Node,
  dropNode: Node,
  dropType: NodeDropType,
  ev: DragEvents
) => {
  // console.log('tree drag end:', dropNode && dropNode.label, dropType)
}

/**
 * 处理节点放置事件
 * @param draggingNode - 正在被拖拽的节点
 * @param dropNode - 目标节点
 * @param dropType - 放置类型 ('prev' | 'next' | 'inner')
 * @param ev - 拖拽事件对象
 */
const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => {
  console.log('tree drop:', dropNode.label, dropType)
}

/**
 * 判断是否允许放置节点
 * @param draggingNode - 正在被拖拽的节点
 * @param dropNode - 目标节点
 * @param type - 放置类型 ('prev' | 'next' | 'inner')
 * @returns {boolean} - 是否允许放置
 */
const allowDrop = (draggingNode: Node, dropNode: Node, type: AllowDropType) => {
  // 限制"Level two 3-1"节点不能作为父节点
  if (dropNode.data.label === 'Level two 3-1') {
    return type !== 'inner' // 允许作为兄弟节点，不允许作为子节点
  } else {
    return true // 其他节点允许所有放置方式
  }
}

/**
 * 判断节点是否允许被拖拽
 * @param draggingNode - 正在被拖拽的节点
 * @returns {boolean} - 是否允许拖拽
 */
const allowDrag = (draggingNode: Node) => {
  // 限制包含"Level three 3-1-1"的节点不能被拖拽
  return !draggingNode.data.label.includes('Level three 3-1-1')
}

/**
 * 树形组件的数据源
 * 结构说明：
 * - label: 节点显示的文本
 * - children: 子节点数组（可选）
 */
const data = [
  {
    label: 'Level one 1',
    children: [
      {
        label: 'Level two 1-1',
        children: [
          {
            label: 'Level three 1-1-1',
          },
        ],
      },
    ],
  },
  {
    label: 'Level one 2',
    children: [
      {
        label: 'Level two 2-1',
        children: [
          {
            label: 'Level three 2-1-1',
          },
        ],
      },
      {
        label: 'Level two 2-2',
        children: [
          {
            label: 'Level three 2-2-1',
          },
        ],
      },
    ],
  },
  {
    label: 'Level one 3',
    children: [
      {
        label: 'Level two 3-1',
        children: [
          {
            label: 'Level three 3-1-1',
          },
        ],
      },
      {
        label: 'Level two 3-2',
        children: [
          {
            label: 'Level three 3-2-1',
          },
        ],
      },
    ],
  },
]
</script>

<template>
  <div>
    推荐文章: <br/>
    element-plus Tree 树形控件https://element-plus.org/zh-CN/component/tree.html
    <br />
    后端接口实现https://www.doubao.com/thread/wd6a14946f6148f2b
    
    <!-- 可拖拽树形组件 -->
    <el-tree
      style="max-width: 600px"
      :allow-drop="allowDrop"
      :allow-drag="allowDrag"
      :data="data"
      draggable
      default-expand-all
      node-key="id"
      @node-drag-start="handleDragStart"
      @node-drag-enter="handleDragEnter"
      @node-drag-leave="handleDragLeave"
      @node-drag-over="handleDragOver"
      @node-drag-end="handleDragEnd"
      @node-drop="handleDrop"
    />
  </div>
</template>

<style scoped>
/* 可添加自定义样式 */
</style>